package com.durian.ui.adapter.multi;

import android.view.LayoutInflater;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.collection.ArrayMap;
import androidx.recyclerview.widget.RecyclerView;

import com.durian.base.utils.StringUtils;

import java.util.ArrayList;

/**
 * 说明：MultiTypePool
 * <p/>
 * 作者：fanly
 * <p/>
 * 类型：Class
 * <p/>
 * 时间：2016/11/28 15:19
 * <p/>
 * 版本：version 1.0
 */
public class MultiTypePool implements TypePool {

    protected ArrayMap<String,MultiTypeWrap> mPoolMap;
    protected LayoutInflater inflater;
    private int autoViewType = 0;
    private int offsetPosition = 0;

    public MultiTypePool() {
        mPoolMap = new ArrayMap<>();
    }

    public String flatClass(Class<?> clazz){
        return clazz.getCanonicalName();
    }

    @Override
    public void offsetPosition(int offset) {
        this.offsetPosition = offset;
    }

    @Override
    public void register(@NonNull Class<?> clazz, @NonNull ViewProvider provider) {
        if (clazz == null) {
            new RuntimeException("You registered class is null!!!");
        }
        if (provider == null) {
            new RuntimeException("You registered provider is null!!!");
        }
        mPoolMap.put(flatClass(clazz),new MultiTypeWrap(clazz,provider));
    }

    @Override
    public RecyclerView.ViewHolder createViewHolder(MultiTypeAdapter adapter,ViewGroup parent, int viewType) {
        if (inflater == null){
            inflater = LayoutInflater.from(parent.getContext());
        }
        if (viewType == -1){
            EmptyItemProvider emptyItemProvider = new EmptyItemProvider();
            return emptyItemProvider.onCreateViewHolder(inflater,parent);
        }else {
            final ViewProvider provider = getProviderByViewType(viewType);
            final RecyclerView.ViewHolder viewHolder = provider.onCreateViewHolder(inflater,parent);
            if (provider.getOnItemClickListener() != null){
                viewHolder.itemView.setOnClickListener(v -> {
                    int position = viewHolder.getLayoutPosition() - offsetPosition;
                    if (position >= 0 && position < adapter.getItemCount()){
                        provider.getOnItemClickListener().onItemClick(position, adapter.get(position));
                    }
                });
            }
            if (provider.getOnItemLongClickListener() != null){
                viewHolder.itemView.setOnLongClickListener(v -> {
                    int position = viewHolder.getLayoutPosition() - offsetPosition;
                    if (position >= 0 && position < adapter.getItemCount()){
                        provider.getOnItemLongClickListener().onItemLongClick(viewHolder,position, adapter.get(position));
                    }
                    return true;
                });
            }
            return viewHolder;
        }
    }

    @Override
    public void bindViewHolder(MultiTypeAdapter adapter, RecyclerView.ViewHolder holder, int position) {
        ViewProvider provider = getViewProviderByItem(adapter.get(position).getClass(),adapter.get(position));
        if (provider != null){
            provider.bindAdapter(adapter);
            provider.convert((MultiItemViewHolder) holder,adapter.get(position),position);
        }
    }

    public ViewProvider getProviderByViewType(int viewType){
        ViewProvider provider = null;
        if (viewType == -1){
            provider = new EmptyItemProvider();
        }else {
            loop:
            for (String name:mPoolMap.keySet()){
                MultiTypeWrap wrap = mPoolMap.get(name);
                if (wrap.isMultiType()){
                    ArrayList<MultiTypeWrap> multiTypeWraps = wrap.getMultiWraps();
                    for (MultiTypeWrap multiTypeWrap:multiTypeWraps){
                        if (multiTypeWrap.getViewType() == viewType){
                            provider = multiTypeWrap.getProvider();
                            break loop;
                        }
                    }
                }else {
                    if (wrap.getViewType() == viewType){
                        provider = wrap.getProvider();
                        break loop;
                    }
                }
            }
        }
        return provider;
    }

    @Override
    public <T> int getViewTypeByClass(@NonNull Class<?> clazz,T item) {
        int viewType = -1;
        autoViewType += 1;
        if (mPoolMap.containsKey(flatClass(clazz))){
            MultiTypeWrap wrap = mPoolMap.get(flatClass(clazz));
            if (wrap.isMultiType()){
                ArrayList<MultiTypeWrap> multiTypeWraps = wrap.getMultiWraps();
                if (wrap.getProvider().withLinker(item) != null){
                    String child = wrap.getProvider().withLinker(item).getCanonicalName();
                    if (child != null){
                        MultiTypeWrap childWrap = null;
                        for (MultiTypeWrap multiTypeWrap:multiTypeWraps){
                            if (StringUtils.isEquals(child,multiTypeWrap.getName())){
                                childWrap = multiTypeWrap;
                                break;
                            }
                        }
                        if (childWrap != null){
                            viewType = childWrap.getViewType();
                            if (viewType == -1){
                                viewType = autoViewType;
                                childWrap.setViewType(viewType);
                            }
                        }
                    }
                }
            }else {
                viewType = wrap.getViewType();
                if (viewType == -1){
                    viewType = autoViewType;
                    wrap.setViewType(viewType);
                }
            }
        }
        return viewType;
    }

    /**
     * 当查找不到支持类型时返回null
     * @param clazz
     * @param item
     * @param <T>
     * @return
     */
    @Override
    public <T> ViewProvider getViewProviderByItem(@NonNull Class<?> clazz, @NonNull T item) {
        ViewProvider provider = null;
        if (mPoolMap.containsKey(flatClass(clazz))){
            MultiTypeWrap wrap = mPoolMap.get(flatClass(clazz));
            if (wrap.isMultiType()){
                ArrayList<MultiTypeWrap> multiTypeWraps = wrap.getMultiWraps();
                if (wrap.getProvider().withLinker(item) != null){
                    String child = wrap.getProvider().withLinker(item).getCanonicalName();
                    if (child != null){
                        loop:
                        for (MultiTypeWrap multiTypeWrap:multiTypeWraps){
                            if (StringUtils.isEquals(child,multiTypeWrap.getName())){
                                provider = multiTypeWrap.getProvider();
                                break loop;
                            }
                        }
                    }
                }
            }else {
                provider = wrap.getProvider();
            }
        }
        return provider;
    }

    @Override
    public void onDestroy() {
        for (String key:mPoolMap.keySet()){
            mPoolMap.get(key).destroy();
        }
    }
}
